package cn.ygh.bbo.system.service.impl;

import cn.ygh.bbo.system.bean.*;
import cn.ygh.bbo.system.service.RolePermissionService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import cn.ygh.bbo.framerwork.core.Grid;
import cn.ygh.bbo.common.exception.TipException;
import cn.ygh.bbo.common.annotation.DataScope;
import cn.ygh.bbo.system.mapper.PermissionMapper;
import cn.ygh.bbo.system.service.PermissionService;
import org.springframework.transaction.annotation.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 描述：权限  ServiceImpl
 * @author ygh
 */
@Service
public class PermissionServiceImpl implements PermissionService{

    private final Logger logger=LoggerFactory.getLogger(getClass());

    @Autowired
    PermissionMapper mapper;

    @Autowired
    RolePermissionService rolePermissionService;

    /**
    * 保存对象
    * @param  permission 对象信息
    * @return
    */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int save(Permission permission) {
        //保存之前通用处理
        beforeCreate(permission);
        permission.def();
        return mapper.insert(permission);
    }

    /**
    * 更新对象
    * @param  permission 对象信息
    * @return
    */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(Permission permission) {
        if(permission.getId()==null){
            throw new TipException("id can not null");
        }
        //更新之前通用处理
        beforeUpdate(permission);
        permission.def();
        return mapper.updateById(permission);
    }

    /**
    * 批量更新
    * @param  permission 对象信息
    * @param ids
    * @return
    */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateBatchByIds(Permission permission, Serializable[] ids) {
        if(ids==null || ids.length==0){
            throw new TipException("ids can not null");
        }
        return mapper.updateBatchByIds(permission,ids);
    }

    /**
    * 根据ID删除对象
    * @param id
    * @return
    */
    @Override
    public int deleteById(Serializable id) {
        if(id==null){
            throw new TipException("id can not null");
        }
        if(checkLink(id)){
            return mapper.deleteById(id);
        }
        return 0;
    }

    /**
    * 删除关联判断
    * @param id
    */
    private boolean checkLink(Serializable id) {
        Integer i=Integer.valueOf(id.toString());
        long count=getCountByParentId(i);
        if (count>0){
            throw new TipException(String.format("子权限列表还存在%s条数据,无法删除",count));
        }
        count=rolePermissionService.getCountByRoleIdAndPermissionId(null, i);
        if (count>0){
            throw new TipException(String.format("角色权限关联还存在%s条数据,无法删除",count));
        }
        return true;
    }

    /**
    * 根据ID数组批量删除对象
    * @param ids
    * @return
    */
    @Override
    public int deleteByIds(Serializable[] ids) {
        if(ids==null || ids.length==0){
            throw new TipException("ids can not null");
        }
        int result=0;
        for (Serializable id:ids){
            result+=deleteById(id);
        }
        return result;
    }

    /**
    * 根据ID获取对象
    * @param id
    * @return
    */
    @Override
    public Permission getById(Serializable id) {
        if(id==null){
            throw new TipException("id can not null");
        }
        return mapper.selectById(id);
    }

    /**
    * 根据ID数组获取对象列表
    * @param ids
    * @return
    */
    @Override
    public List<Permission> listfindByIn(Serializable[] ids) {
        if(ids==null || ids.length==0){
            throw new TipException("ids can not null");
        }
        return mapper.selectBatchIds(Arrays.asList(ids));
    }

    /**
    * 根据对象信息获取满足条件的对象列表
    * @param  permission 对象信息
    * @param pageable 分页条件为空则不分页
    * @return
    */
    @DataScope
    @Override
    public List<Permission> listfind(Permission permission, Pageable pageable) {
        if (pageable!=null && pageable.getPageNumber()!=0){
            PageHelper.startPage(pageable.getPageNumber()
                    , pageable.getPageSize(), false);
        }
        return mapper.selectByObj(permission);
    }

    /**
    * 根据对象信息获取满足条件的对象列表和总数
    * @param  permission 对象信息
    * @param pageable 分页条件
    * @return
    */
    @DataScope
    @Override
    public Grid listGrid(Permission permission, Pageable pageable) {
        PageHelper.startPage(pageable.getPageNumber()
                , pageable.getPageSize(), true);
        List<Permission> permissions = mapper.selectByObj(permission);
        PageInfo<Permission>pageInfo=new PageInfo<>(permissions);
        Grid grid=new Grid();
        grid.setTotal((int) pageInfo.getTotal());
        grid.setRows(pageInfo.getList());
        return grid;
    }

    /**
     * 获取角色的相关操作权限列表
     *
     * @param roles
     * @return
     */
    @Override
    public List<Permission> listfindByRoles(List<Role> roles) {
        if (CollectionUtils.isEmpty(roles)){
            return new ArrayList<>();
        }
        //获取所有的权限关联列表
        List<Integer>roleIds=roles.stream().map(e->e.getId()).collect(Collectors.toList());
        List<RolePermission>rolePermissions=rolePermissionService.listfindByRoleIds(roleIds);
        List<Integer>ids=rolePermissions.stream().map(e->e.getPermissionId()).collect(Collectors.toList());
        Permission params=new Permission();
        params.setIds(ids);
        params.setType(5);
        return listfind(params, null);
    }

    /**
     * 获取角色相关菜单和页面权限
     *
     * @param roles
     * @return
     */
    @Override
    public List<Permission> listfindMenusByRoles(List<Role> roles) {
        if (CollectionUtils.isEmpty(roles)){
            return new ArrayList<>();
        }
        //获取所有的权限关联列表
        List<Integer>roleIds=roles.stream().map(e->e.getId()).collect(Collectors.toList());
        List<RolePermission>rolePermissions=rolePermissionService.listfindByRoleIds(roleIds);
        List<Integer>ids=rolePermissions.stream().map(e->e.getPermissionId()).collect(Collectors.toList());
        Permission params=new Permission();
        params.setTypes(Arrays.asList(1,3));
        params.setIds(ids);
        return listfind(params, null);
    }

    /**
     * 获取所有的菜单和页面权限
     *
     * @return
     */
    @Override
    public List<Permission> listfindMenusAll() {
        Permission params=new Permission();
        params.setTypes(Arrays.asList(1,3));
        return listfind(params, null);
    }

    /**
     * 子权限个数
     *
     * @param parentId
     * @return
     */
    @Override
    public long getCountByParentId(Integer parentId) {
        Permission params=new Permission();
        params.setParentId(parentId);
        return mapper.selectCountByObj(params);
    }

    /**
     * 获取所有下属权限
     *
     * @param parentId
     * @return
     */
    @Override
    public List<Permission> listfindByParentId(Integer parentId) {
        if (parentId==null || new Integer(0).equals(parentId)){
            return new ArrayList<>();
        }
        //获取所有的部门
        List<Permission>permissions=listfind(new Permission(), null);
        List<Permission>result=new ArrayList<>();
        List<Integer>parants=new ArrayList<>();
        parants.add(parentId);
        while (true){
            if (parants.size()==0){
                break;
            }
            List<Permission>children=permissions.stream()
                    .filter(e->parants.contains(e.getParentId())).collect(Collectors.toList());
            parants.clear();
            for (Permission permission:children){
                //防止循环调用
                Permission p=result.stream().filter(e->e.getId()
                        .equals(permission.getId())).findFirst().orElse(null);
                if (p==null){
                    result.add(permission);
                    parants.add(permission.getId());
                }
            }
        }
        return result;
    }
}
